home *** CD-ROM | disk | FTP | other *** search
Wrap
#define REVISION "40.3beta" #define AUTHOR "Miloslaw Smyk" #define VERNUM 40 #define REVNUM 3 #define PROGNAME "wfmhcybergfx_r3d.library" #define NAME_RECOG "Real 3D " #include <string.h> #include <exec/types.h> #include <exec/tasks.h> #include <exec/execbase.h> #include <exec/memory.h> #include <exec/nodes.h> #include <graphics/modeid.h> #include <intuition/intuitionbase.h> #include <intuition/intuition.h> #include <intuition/screens.h> #include <clib/exec_protos.h> #include <pragmas/exec_sysbase_pragmas.h> #include <clib/intuition_protos.h> #include <pragmas/intuition_pragmas.h> #include <cybergraphics/cybergraphics.h> #include <pragmas/cybergraphics_pragmas.h> #include <clib/alib_protos.h> #include <clib/macros.h> #include <proto/dos.h> #include <proto/intuition.h> #include <proto/graphics.h> #include <proto/asl.h> #include <proto/cybergraphics.h> #include <proto/gadtools.h> #include <dos.h> #include "wfmhcybergfx_key.h" #include "key.h" /* includes for the GUI */ #include "realprefs.h" /* we require 3.0 to work */ long __oslibversion = 39; #define VAR_PATH "ENV:wfmhcybergfx_r3d.prefs" #define VAR_SAVE_PATH "ENVARC:wfmhcybergfx_r3d.prefs" #define VAR_LINE_SIZE 80 #define KEYPATH_VAR_SIZE 256 #define KEYPATH_VAR_NAME "KEYPATH" #define KEY_NAME "wfmhcybergfx_key.library" #define TEMPLATE "DITHER/K,NOABOUT/S,POSX/N,POSY/N" #define OPT_DITHER 0 #define OPT_NOABOUT 1 #define OPT_POSX 2 #define OPT_POSY 3 #define OPT_COUNT 4 /* struct R3DHandle { struct Node h_node; struct Screen *RenderScr; struct Window *wnd; UBYTE depth; UWORD size_x, size_y; struct Task *task; SHORT *line; int line_width; }; */ struct Library *SysBase; struct Library *CyberGfxBase; struct KeyBase *KeyBase; struct List handle_list; struct SignalSemaphore sem; int stop; int count; ULONG AboutBox = TRUE; static const char version[] = "\0$VER: " PROGNAME " " REVISION " " __AMIGADATE__ " © 1995-97 " AUTHOR " / World Federation of Mad Hackers"; char registration_info[] = "Unfortunately you are not allowed\n\ to use ordered and Floyd-Steinberg\n\ dithering modes in the unregistered\n\ version. Rendering to screens bigger\n\ than 640x512 is also disabled, and you\n\ can only render as much as 50 times.\n\ About box cannot be disabled, either.\n\ \n\ To register, please send $20 or 30DM to\n\ \n\ Miloslaw Smyk\n\ ul. Orawska 22/34\n\ 70-131 Szczecin\n\ POLAND\n\ \n\ Thank you."; APTR __asm __saveds R3DInitDspDrv(void); void __asm __saveds R3DFreeDspDrv(register __a0 APTR handle); void __asm __saveds R3DSetMode(register __a0 APTR handle); void __asm __saveds R3DGetSize(register __a0 APTR handle,register __a1 int *x,register __d0 int *y,register __a5 char *data_seg); void __asm __saveds R3DWriteLine(register __a0 APTR handle,register __a1 int *buffer,register __a2 int len,register __d0 int x,register __d1 int y); void __asm __saveds R3DReadLine(register __a0 APTR handle,register __a1 int *buffer,register __a2 int len,register __d0 int x,register __d1 int y); void __asm __saveds R3DClsScr(register __a0 APTR handle,register __a1 ULONG color); int * __asm __saveds R3DCustomSave(register __a0 APTR handle,register __a1 char *name,register __a2 int x,register __d0 int y,register __d1 int w,register __d2 int h); int __asm __saveds R3DInitRen(register __a0 struct R3DHandle *handle); void __asm __saveds R3DEndRen(register __a0 struct R3DHandle *handle); int __asm __saveds R3DEndRow(register __a0 struct R3DHandle *handle, register __a1 int y); void __asm __saveds R3DGetAspect(register __a0 struct R3DHandle *handle,register __a1 int *w ,register __d0 int *h); int __asm __saveds R3DExtF(register __a0 struct R3DHandle *handle); int HandleRealPrefsIDCMP( void ) { struct IntuiMessage *m; int (*func)(); BOOL running = TRUE; ULONG cycle, about; WaitPort(RealPrefsWnd->UserPort); while( m = GT_GetIMsg( RealPrefsWnd->UserPort )) { CopyMem(( char * )m, ( char * )&RealPrefsMsg, (long)sizeof( struct IntuiMessage )); GT_ReplyIMsg( m ); switch ( RealPrefsMsg.Class ) { case IDCMP_CHANGEWINDOW: RealPrefsLeft = RealPrefsWnd->LeftEdge; RealPrefsTop = RealPrefsWnd->TopEdge; break; case IDCMP_REFRESHWINDOW: GT_BeginRefresh( RealPrefsWnd ); RealPrefsRender(); GT_EndRefresh( RealPrefsWnd, TRUE ); break; case IDCMP_CLOSEWINDOW: running = RealPrefsCloseWindow(); break; case IDCMP_GADGETUP: func = ( void * )(( struct Gadget * )RealPrefsMsg.IAddress )->UserData; running = func(); break; case IDCMP_VANILLAKEY: switch(RealPrefsMsg.Code) { case 'a': case 'A': GT_GetGadgetAttrs(RealPrefsGadgets[4], RealPrefsWnd, NULL, GTCB_Checked, &about); about = !about; GT_SetGadgetAttrs(RealPrefsGadgets[4], RealPrefsWnd, NULL, GTCB_Checked, about); running = Gadget40Clicked(); break; case 's': case 'S': running = Gadget10Clicked(); break; case 'u': case 'U': running = Gadget30Clicked(); break; case '\x1b': case 'c': case 'C': running = Gadget20Clicked(); break; case 'd': case 'D': GT_GetGadgetAttrs(RealPrefsGadgets[0], RealPrefsWnd, NULL, GTCY_Active, &cycle); if(RealPrefsMsg.Qualifier & (IEQUALIFIER_LSHIFT | IEQUALIFIER_RSHIFT)) cycle = cycle == 0 ? 2 : cycle - 1; else cycle = cycle == 2 ? 0 : cycle + 1; GT_SetGadgetAttrs(RealPrefsGadgets[0], RealPrefsWnd, NULL, GTCY_Active, cycle); running = Gadget00Clicked(); break; } break; } } return( running ); } void msg_req(char *text) { static struct EasyStruct myES = { sizeof(struct EasyStruct), 0, NULL, NULL, 0 }; struct Window *wnd; ULONG lock; myES.es_Title="Information"; myES.es_TextFormat=text; myES.es_GadgetFormat="OK"; lock = LockIBase(0); wnd = IntuitionBase->FirstScreen->FirstWindow; UnlockIBase(lock); EasyRequest(wnd, &myES, NULL); } /* prefs parser done with ReadArgs() */ void read_prefs(void) { BPTR fh; char var[VAR_LINE_SIZE]; char *dither_names = "none\1ordered\1fs"; LONG opts[OPT_COUNT]; struct RDArgs *rdargs; ULONG dither_state; int len; if(fh = Open(VAR_PATH, MODE_OLDFILE)) { if(rdargs = (struct RDArgs *)AllocDosObject(DOS_RDARGS, NULL)) { /* we substract -1 because later we may need to add one more byte at the end of the buffer */ if(FGets(fh, var, sizeof(var) - 1)) { // so that ReadArgs() will work if line was terminated by EOF len = strlen(var); if(len && var[len - 1] != '\n') { var[len] = '\n'; var[++len] = '\0'; } memset(opts, 0, sizeof(opts)); rdargs->RDA_Flags |= RDAF_NOPROMPT; rdargs->RDA_Source.CS_Buffer = var; rdargs->RDA_Source.CS_Length = len; if(rdargs = ReadArgs(TEMPLATE, opts, rdargs)) { if(opts[OPT_NOABOUT] && KeyBase) AboutBox = FALSE; if(opts[OPT_POSX]) RealPrefsLeft = *(LONG *)opts[OPT_POSX]; if(opts[OPT_POSY]) RealPrefsTop = *(LONG *)opts[OPT_POSY]; if(opts[OPT_DITHER]) { switch(strstr(dither_names, strlwr((char *)opts[OPT_DITHER])) - dither_names) { case 0: dither_state = DT_NONE; break; case 5: dither_state = DT_ORDERED; break; case 13: dither_state = DT_FS; break; default: dither_state = DT_NONE; msg_req("Error:\nUnknown dither type in prefs file."); break; } if(KeyBase) SetDitherType(dither_state); } FreeArgs(rdargs); } else msg_req("Error:\nUnable to parse prefs file."); } FreeDosObject(DOS_RDARGS, rdargs); } Close(fh); } } int check_task(struct Task *task) { struct Task *node; int ret_val = FALSE; if(FindTask(NULL) == task) return(TRUE); Disable(); for(node = (struct Task *)((struct ExecBase *)SysBase)->TaskReady.lh_Head; node->tc_Node.ln_Succ; node = (struct Task *)node->tc_Node.ln_Succ) if(node == task) ret_val = TRUE; if(!ret_val) for(node = (struct Task *)((struct ExecBase *)SysBase)->TaskWait.lh_Head; node->tc_Node.ln_Succ; node = (struct Task *)node->tc_Node.ln_Succ) if(node == task) ret_val = TRUE; Enable(); return(ret_val); } struct R3DHandle *get_handle(struct R3DHandle *first, struct Task *task) { struct R3DHandle *node, *temp, *ret_val = NULL; ObtainSemaphore(&sem); node = first; while(node->h_node.ln_Succ) { if(node->task && !check_task(node->task)) { /* remove task info from R3DHandles list */ temp = (struct R3DHandle *)node->h_node.ln_Succ; Remove((struct Node *)node); if(node->line) FreeVec(node->line); FreeVec(node); node = temp; } else node = (struct R3DHandle *)node->h_node.ln_Succ; } for(node = first; node->h_node.ln_Succ; node = (struct R3DHandle *)node->h_node.ln_Succ) if(node->task && node->task == task) { ret_val = node; break; } if(!ret_val && (node = AllocVec(sizeof(struct R3DHandle), MEMF_CLEAR | MEMF_ANY))) { node->task = task; AddTail(&handle_list, (struct Node *)node); ret_val = node; } ReleaseSemaphore(&sem); return(ret_val); } void __asm __saveds putch_proc(register __d0 char c, register __a3 char **buf) { **buf = c; (*buf)++; } APTR __asm __saveds R3DInitDspDrv() { struct R3DHandle *R3DH; char buffer[400], *buf = buffer; struct UserInfo *user; if(KeyBase) user = GetUserInfo(); if(R3DH = AllocVec(sizeof(struct R3DHandle), MEMF_CLEAR | MEMF_PUBLIC)) { ObtainSemaphore(&sem); AddTail(&handle_list, (struct Node *)R3DH); ReleaseSemaphore(&sem); read_prefs(); if(KeyBase) RawDoFmt("wfmhcybergfx_r3d.library\n\ by Miloslaw Smyk\n\n\ Version " REVISION ", compiled on " __DATE__ "\n\n\ This copy (#%04ld) is registered to:\n\n\ %s\n\ %s\n\ %s\n\ %s\n\ \nPlease do not redistribute.", user, putch_proc, &buf); else RawDoFmt("wfmhcybergfx_r3d.library\n\ by Miloslaw Smyk\n\n\ Version " REVISION ", compiled on " __DATE__ "\n\n\ Unregistered version.", NULL, putch_proc, &buf); if(AboutBox) msg_req(buffer); if(KeyBase) InitDithering(); return((APTR)R3DH); } } void __asm __saveds R3DFreeDspDrv(register __a0 struct R3DHandle *handle) { struct R3DHandle *node, *temp; if(handle) { ObtainSemaphore(&sem); node = handle; while(node->h_node.ln_Succ) { /* remove task info from R3DHandles list */ temp = (struct R3DHandle *)node->h_node.ln_Succ; Remove((struct Node *)node); if(node->line) FreeVec(node->line); FreeVec(node); node = temp; } ReleaseSemaphore(&sem); } } /* routine when gadget "_Dithering" is clicked. */ int Gadget00Clicked( void ) { ULONG cycle; GT_GetGadgetAttrs(RealPrefsGadgets[0], RealPrefsWnd, NULL, GTCY_Active, &cycle); if(cycle != DT_NONE && !KeyBase) { msg_req(registration_info); GT_SetGadgetAttrs(RealPrefsGadgets[0], RealPrefsWnd, NULL, GTCY_Active, DT_NONE); } return(TRUE); } int save_prefs(char *name) { BPTR fh; char *dither_name[3] = { "FS", "ORDERED", "NONE" }; int err; char buffer[200], *buf; buf = buffer; err = TRUE; if(fh = Open(name, MODE_NEWFILE)) { if(-1 != FPrintf((LONG)fh, "DITHER=%s %s%ld %ld\n", dither_name[KeyBase ? KeyBase->dither_type : DT_NONE], (AboutBox ? "" : "NOABOUT "), RealPrefsLeft, RealPrefsTop)) err = FALSE; Close(fh); } if(err) { RawDoFmt("Error:\nUnable to save prefs file as\n%s", &name, putch_proc, &buf); msg_req(buffer); return(TRUE); } return(FALSE); } /* routine when gadget "_Save" is clicked. */ int Gadget10Clicked( void ) { ULONG cycle; GT_GetGadgetAttrs(RealPrefsGadgets[0], RealPrefsWnd, NULL, GTCY_Active, &cycle); GT_GetGadgetAttrs(RealPrefsGadgets[4], RealPrefsWnd, NULL, GTCB_Checked, &AboutBox); if(KeyBase) SetDitherType(cycle); save_prefs(VAR_PATH); /* do not close window if prefs can't be saved to disk */ return(save_prefs(VAR_SAVE_PATH)); } /* routine when gadget "_Cancel" is clicked. */ int Gadget20Clicked( void ) { return(FALSE); } /* routine when gadget "_Use" is clicked. */ int Gadget30Clicked( void ) { ULONG cycle; GT_GetGadgetAttrs(RealPrefsGadgets[0], RealPrefsWnd, NULL, GTCY_Active, &cycle); GT_GetGadgetAttrs(RealPrefsGadgets[4], RealPrefsWnd, NULL, GTCB_Checked, &AboutBox); if(KeyBase) SetDitherType(cycle); save_prefs(VAR_PATH); return(FALSE); } /* checkbox "About" changed state */ int Gadget40Clicked( void ) { ULONG about; GT_GetGadgetAttrs(RealPrefsGadgets[4], RealPrefsWnd, NULL, GTCB_Checked, &about); if(about == FALSE && !KeyBase) { msg_req(registration_info); GT_SetGadgetAttrs(RealPrefsGadgets[4], RealPrefsWnd, NULL, GTCB_Checked, TRUE); } return(TRUE); } int RealPrefsCloseWindow( void ) { /* routine for "IDCMP_CLOSEWINDOW". */ return(FALSE); } void __asm __saveds R3DSetMode(register __a0 struct R3DHandle *handle) { ULONG lock; struct Screen *scr; lock = LockIBase(0); scr = IntuitionBase->FirstScreen; UnlockIBase(lock); if(!(scr->Flags & PUBLICSCREEN)) scr = NULL; if(!SetupScreen(scr)) { if(!OpenRealPrefsWindow()) { while(HandleRealPrefsIDCMP()); CloseRealPrefsWindow(); } CloseDownScreen(); } } void __asm __saveds R3DGetSize(register __a0 struct R3DHandle *handle,register __a1 int *x,register __d0 int *y, register __a5 char *data_seg) { ULONG lock; struct Window *wnd; struct Task *this; struct Task *task = NULL; int *stc = (int *)getreg(REG_A7); /* let's get the address of currently selected window */ lock = LockIBase(0); wnd = IntuitionBase->ActiveWindow; UnlockIBase(lock); /* If user just toggled "rendering output" gadget in Settings window to "External", ** we skip further processing. */ if(strncmp(wnd->Title, NAME_RECOG, sizeof(NAME_RECOG) - 1)) { if(strncmp(((struct Task *)wnd->UserPort->mp_SigTask)->tc_Node.ln_Name, "View", 4)) { ULONG lock; struct Screen *scr; struct Window *w; lock = LockIBase(0); scr = IntuitionBase->FirstScreen; for(w = scr->FirstWindow; w; w = w->NextWindow) if(!strncmp(((struct Task *)w->UserPort->mp_SigTask)->tc_Node.ln_Name, "View", 4)) { wnd = w; UnlockIBase(lock); goto out; } UnlockIBase(lock); return; } out: /* if we are called from a process (what in fact means Real's main thread), we take ** a different route */ this = FindTask(NULL); if(this->tc_Node.ln_Type == NT_PROCESS) { if(stc[34]) { task = ((struct Message*)stc[34])->mn_ReplyPort->mp_SigTask; handle = get_handle(handle, task); } handle->wnd = wnd; } else { handle = get_handle(handle, this); /* set DrawTask's R3DHandle address */ *(struct R3DHandle **)&data_seg[0x2e] = handle; count++; if(handle->line) memset(handle->line, 0, sizeof(SHORT) * (handle->line_width + 2) * 3); } handle->size_x = *x = handle->wnd->Width - handle->wnd->BorderLeft - handle->wnd->BorderRight; handle->size_y = *y = handle->wnd->Height - handle->wnd->BorderTop - handle->wnd->BorderBottom; handle->depth = GetCyberIDAttr(CYBRIDATTR_DEPTH, GetVPModeID(&handle->wnd->WScreen->ViewPort)); if(task && handle->depth >= 15) *(int *)&data_seg[0x26c] = 0; /* force Real to take new window's size under consideration :) */ } else *x = *y = 1; } void __asm __saveds R3DWriteLine(register __a0 struct R3DHandle *handle,register __a1 int *buffer,register __a2 int len,register __d0 int x, register __d1 int y) { int *a = 0; if(!handle) *a = 0xeeee; if(handle->wnd) { if(handle->depth < 15) { msg_req("This screen is not deep enough\nto allow true-color rendering.\nPlease open the one with higher\ncolor depth (at least 15 bits)."); stop = TRUE; return; } if(KeyBase) DitherLine(handle, (UBYTE *)buffer, len, x, y); else if(handle->wnd->WScreen->Width - 40 > 600 || handle->wnd->WScreen->Height + 51 > 563 || (count + 11 > 61)) { msg_req(registration_info); stop = TRUE; return; } WritePixelArray(buffer, 0, 0, len * 4, handle->wnd->RPort, x, y, len, 1, RECTFMT_RGBA); } } void __asm __saveds R3DReadLine(register __a0 struct R3DHandle *handle,register __a1 int *buffer,register __a2 int len,register __d0 int x,register __d1 int y) { if(handle->wnd && handle->depth >= 15) { if(handle->wnd->Flags & WFLG_GIMMEZEROZERO) ReadPixelArray(buffer, 0, 0, len * 4, handle->wnd->RPort, x, y, len, 1, RECTFMT_RGBA); else ReadPixelArray(buffer, 0, 0, len * 4, handle->wnd->RPort, x + handle->wnd->BorderLeft, y + handle->wnd->BorderTop, len, 1, RECTFMT_RGBA); } } void __asm __saveds R3DClsScr(register __a0 struct R3DHandle *handle,register __a1 ULONG color) { } int *__asm __saveds R3DCustomSave(register __a0 APTR handle,register __a1 char *name,register __a2 int x,register __d0 int y,register __d1 int w,register __d2 int h) { return(NULL); } int __asm __saveds R3DInitRen(register __a0 struct R3DHandle *handle) { return(TRUE); } void __asm __saveds R3DEndRen(register __a0 struct R3DHandle *handle) { } int __asm __saveds R3DEndRow(register __a0 struct R3DHandle *handle, register __a1 int y) { if(stop) { stop = FALSE; return(FALSE); } return(TRUE); } void __asm __saveds R3DGetAspect( register __a0 struct R3DHandle *handle, register __a1 int *w , register __d0 int *h) { *h = *w = 1; } int __asm __saveds R3DExtF(register __a0 struct R3DHandle *handle) { return(NULL); } int __saveds __UserLibInit(void) { char *var; SysBase = (*(struct Library **)4); if(CyberGfxBase = OpenLibrary("cybergraphics.library", 40L)) { if(!(KeyBase = (struct KeyBase *)OpenLibrary(KEY_NAME, 40L))) { if(var = AllocVec(KEYPATH_VAR_SIZE, MEMF_ANY)) { if(-1 != GetVar(KEYPATH_VAR_NAME, var, KEYPATH_VAR_SIZE, NULL)) { if(AddPart(var, KEY_NAME, KEYPATH_VAR_SIZE)) KeyBase = (struct KeyBase *)OpenLibrary(var, 40L); } FreeVec(var); } } NewList(&handle_list); InitSemaphore(&sem); stop = FALSE; return(0); } return(1); } void __saveds __UserLibCleanup(void) { if(KeyBase) CloseLibrary((struct Library *)KeyBase); if(CyberGfxBase) CloseLibrary(CyberGfxBase); }